/*
  Program: Mine Mayhem
  File:    mainmenu.h
  Date:    July, 1996 to February,   1997,    version 1.00
	   26 October to 3 December,	      version 2.00
	   8 December to 4 January,  2001,    version 2.10
	   15 January,			      version 2.11
	   18 September to 16 December, 2006, version 2.90

  The main menu.

  Freeware, Copyright 2006 Jason Hood.
*/

#include "mainmenu.h"
#include "menuicon.h"
#include <tws/help.h>
#include "minefld.h"
#include "board.h"
#include "options.h"
#include "sound.h"
#include "msgwin.h"
#include <stdio.h>

#define VERSION "2.90"

#define ID_SEPARATOR         -1

#define ID_GAME_STYLE	     16
  #define ID_GAME_SQUARES    (21+SQUARES)
  #define ID_GAME_HEXAGONS   (21+HEXAGONS)
  #define ID_GAME_HEXAGONAL  (21+HEXAGONAL)
#define ID_GAME_TYPE	     17
  #define ID_GAME_CLEAR      18
  #define ID_GAME_CROSS      19
#define ID_GAME_BEGINNER     11
#define ID_GAME_INTERMEDIATE 12
#define ID_GAME_EXPERT       13
#define ID_GAME_CUSTOM       14
#define ID_GAME_RANDOM        1
  #define ID_GAME_RANDOM2     2
  #define ID_GAME_RANDOM3     3
  #define ID_GAME_RANDOM4     4
  #define ID_GAME_RANDOM5     5
  #define ID_GAME_RANDOM6     6
  #define ID_GAME_RANDOM7     7
  #define ID_GAME_RANDOM8     8
  #define ID_GAME_RANDOM9     9
  #define ID_GAME_RANDOM10   10
#define ID_GAME_EXIT	     15

#define ID_OPTIONS_TIMES     30
#define ID_OPTIONS_3BVPS     31
#define ID_OPTIONS_STATS     32
#define ID_OPTIONS_CONFIG    33
#define ID_OPTIONS_SOUND     34

#define ID_HELP_NONE	     40
#define ID_HELP_CLUES	     41
#define ID_HELP_WHERE	     42
#define ID_HELP_WHAT	     43
#define ID_HELP_CONTENTS     44
#define ID_HELP_ABOUT	     45


#define ID_STYLE_BUTTON      50
#define ID_GAME_BUTTON	     51
#define ID_AUTO_BUTTON	     52



extern BYTE HighLightColour;


PopupMenuRes StyleMenuRes[] =
{
  { "&Squares",   ID_GAME_SQUARES,   0, 0 },
  { "&Hexagons",  ID_GAME_HEXAGONS,  0, 0 },
  { "He&xagonal", ID_GAME_HEXAGONAL, 0, 0 }
};


PopupMenuRes TypeMenuRes[] =
{
  { "C&lear",     ID_GAME_CLEAR, 0, 0 },
  { "Cr&oss",     ID_GAME_CROSS, 0, 0 }
};


PopupMenuRes RandomMenuRes[] =
{
  { " &2", ID_GAME_RANDOM2,  0, 0 },
  { " &3", ID_GAME_RANDOM3,  0, 0 },
  { " &4", ID_GAME_RANDOM4,  0, 0 },
  { " &5", ID_GAME_RANDOM5,  0, 0 },
  { " &6", ID_GAME_RANDOM6,  0, 0 },
  { " &7", ID_GAME_RANDOM7,  0, 0 },
  { " &8", ID_GAME_RANDOM8,  0, 0 },
  { " &9", ID_GAME_RANDOM9,  0, 0 },
  { "1&0", ID_GAME_RANDOM10, 0, 0 }
};


#define ITEMS(menu) sizeof(menu)/sizeof(*menu)
#define POPUP(menu) ITEMS(menu), menu

PopupMenuRes GameMenuRes[] =
{
  { "&Style",        ID_GAME_STYLE,        POPUP(StyleMenuRes) },
  { "&Type",         ID_GAME_TYPE,         POPUP(TypeMenuRes) },
  { NULL,            ID_SEPARATOR,         0, 0 },
  { "&Beginner",     ID_GAME_BEGINNER,     0, 0 },
  { "&Intermediate", ID_GAME_INTERMEDIATE, 0, 0 },
  { "&Expert",       ID_GAME_EXPERT,       0, 0 },
  { "&Custom",       ID_GAME_CUSTOM,       0, 0 },
  { "&Random",       ID_GAME_RANDOM,       POPUP(RandomMenuRes) },
  { NULL,	     ID_SEPARATOR,	   0, 0 },
  { "E&xit",         ID_GAME_EXIT,         0, 0 }
};


PopupMenuRes OptionsMenuRes[] =
{
  { "&Times",         ID_OPTIONS_TIMES,  0, 0 },
  { "&3BV/s",         ID_OPTIONS_3BVPS,  0, 0 },
  { "&Statistics",    ID_OPTIONS_STATS,  0, 0 },
  { NULL,	      ID_SEPARATOR,	 0, 0 },
  { "&Configuration", ID_OPTIONS_CONFIG, 0, 0 },
  { "So&und",         ID_OPTIONS_SOUND,  0, 0 }
};


PopupMenuRes HelpMenuRes[] =
{
  { "   None",   ID_HELP_NONE,     0, 0 },
  { "   Clues",  ID_HELP_CLUES,    0, 0 },
  { "   Where",  ID_HELP_WHERE,    0, 0 },
  { "   What",   ID_HELP_WHAT,     0, 0 },
  { NULL,	 ID_SEPARATOR,	   0, 0 },
  { "&Contents", ID_HELP_CONTENTS, 0, 0 },
  { NULL,	 ID_SEPARATOR,	   0, 0 },
  { "&About",    ID_HELP_ABOUT,    0, 0 }
};


MenuRes MainMenuRes[] =
{
  { "&Game",    POPUP(GameMenuRes)    },
  { "&Options", POPUP(OptionsMenuRes) },
  { "&Help",    POPUP(HelpMenuRes)    }
};


DEFINE_RESPONSE_TABLE(MainMenu, AutoMenu)
  if (ev->Type == W_COMMAND &&
      (ev->p1 >= ID_GAME_SQUARES && ev->p1 < ID_GAME_SQUARES + NoGameStyles))
  {
    cmGameStyle(ev->p1 - ID_GAME_SQUARES);
    return true;
  }
  if (ev->Type == W_COMMAND &&
      ev->p1 >= ID_GAME_CLEAR && ev->p1 <= ID_GAME_CROSS)
  {
    cmGameType(ev->p1 - ID_GAME_CLEAR);
    return true;
  }
  if (ev->Type == W_COMMAND &&
      (ev->p1 >= ID_GAME_RANDOM2 && ev->p1 <= ID_GAME_CUSTOM))
  {
    cmGameNew(ev->p1);
    return true;
  }
  E_COMMAND(ID_GAME_EXIT,      cmGameExit)
  E_COMMAND(ID_OPTIONS_TIMES,  cmOptionsTimes)
  E_COMMAND(ID_OPTIONS_3BVPS,  cmOptions3BVps)
  E_COMMAND(ID_OPTIONS_STATS,  cmOptionsStats)
  E_COMMAND(ID_OPTIONS_CONFIG, cmOptionsConfig)
  E_COMMAND(ID_OPTIONS_SOUND,  cmOptionsSound)
  if (ev->Type == W_COMMAND &&
      (ev->p1 >= ID_HELP_NONE && ev->p1 <= ID_HELP_WHAT))
  {
    Main->cmHints(ev->p1 - ID_HELP_NONE);
    return true;
  }
  E_COMMAND(ID_HELP_CONTENTS,  cmHelpContents)
  E_COMMAND(ID_HELP_ABOUT,     cmHelpAbout)
END_RESPONSE_TABLE


DEFINE_RESPONSE_TABLE(MainMenuWindow, Window)
  E_BUTTONUP(ID_STYLE_BUTTON, cmStyle)
  E_BUTTONUP(ID_GAME_BUTTON,  cmGame)
  E_BUTTONUP(ID_AUTO_BUTTON,  cmAuto)
  E_TIMER
END_RESPONSE_TABLE


MainMenu::MainMenu(Window* parent, int x, int y, int w) :
    AutoMenu(parent, MainMenuRes, ITEMS(MainMenuRes), x, y, w)
{
  HelpMenuRes[Hints].Text[0] = '[';
  HelpMenuRes[Hints].Text[1] = ']';
}

void MainMenu::cmGameStyle(int style)
{
  if (GameStyle != style)
  {
    GameStyle = style-1;
    Main->cmStyle();
  }
}

void MainMenu::cmGameType(int type)
{
  Game = type;
  Main->cmGame(true);
  field->NewGame();
}

void MainMenu::cmGameNew(int level)
{
  field->NewGame(level);
}

void MainMenu::cmGameExit()
{
  ws.StopRunningEvents();
}

void MainMenu::cmOptionsTimes()
{
  field->times.Display(field->level, -1);
}

void MainMenu::cmOptions3BVps()
{
  field->times.Display(field->level, -2);
}

void MainMenu::cmOptionsStats()
{
  field->times.Display(field->level, -3);
}

void MainMenu::cmOptionsConfig()
{
  OptionDlg().Run();
  Main->cmGame(true);
  Main->cmAuto(true);
}

void MainMenu::cmOptionsSound()
{
  SoundDlg().Run();
}

void MainMenu::cmHelpContents()
{
  HelpDataBase* helpdb;
  HelpWindow* helpwin;

  helpdb = new HelpDataBase("mine.hlp");
  helpwin = new HelpWindow(NULL, helpdb, "Contents", 100, 50,
			   ws.GetDeskWidth()-100, ws.GetDeskHeight()-50);
  helpwin->Setup();
}

void MainMenu::cmHelpAbout()
{
  MessageWindow About("About");
  About.Write("Mine Mayhem", HighLightColour, SysFontBoldItallic);
  About.Write("Version "VERSION);
  About.Write();
  About.Write("Jason Hood", 0, SysFontBold);
  About.Write();
  About.Write("Freeware");
  About.Write("Copyright 2006");
  About.Run();
}


MainMenuWindow::MainMenuWindow() :
  Window(NULL, NULL, 0, 0, ws.GetDeskWidth()-1, SysFont->height+FWIDTH*2+4-1,
         WA_VISABLE | WA_BORDER)
{
  int hyt = SysFont->height+4,
      wid = MAX(hyt, MENUICONW+4),
      ox = (ws.GetDeskWidth() - (wid*3+4))/2,
      oy = FWIDTH,
      icon;

  menu = new MainMenu(this, FWIDTH+2, FWIDTH+2, ox-6);

  switch (GameStyle)
  {
    default:
    case SQUARES:   icon = MENUSQUARES;   break;
    case HEXAGONS:  icon = MENUHEXAGONS;  break;
    case HEXAGONAL: icon = MENUHEXAGONAL; break;
  }
  StyleButton = new IconButton(this, ID_STYLE_BUTTON, ox, oy,
				     ox+wid-1, oy+hyt-1, MenuIcon[icon]);
  ox += wid+4;
  icon = (Game == CROSS)      ? MENUCROSS :
	 (Start == PERIMETER) ? MENUPERIMETER :
	 (field->canWrap())   ? MENUWRAP : MENUCLEAR;
  GameButton = new IconButton(this, ID_GAME_BUTTON, ox, oy,
				    ox+wid-1, oy+hyt-1, MenuIcon[icon]);
  ox += wid+4;
  icon = isAutoMark + isAutoOpen*2 + MENUNONE;
  AutoButton = new IconButton(this, ID_AUTO_BUTTON, ox, oy,
				    ox+wid-1, oy+hyt-1, MenuIcon[icon]);

  gettime(&old_time);
  char buffer[6];
  sprintf(buffer, "%d:%02d", old_time.ti_hour, old_time.ti_min);
  wid = 7*SysFont->width;
  tym = new StaticText(this, buffer, w-FWIDTH-2-wid, FWIDTH+2, wid);
  ws.StartTimer(this, 250);

  Paint();
  RefreshWindow();
}

MainMenuWindow::~MainMenuWindow()
{
  delete menu;
  delete StyleButton;
  delete GameButton;
  delete AutoButton;
  delete tym;
}


// Use the style button to toggle between the square and hexagon games.
void MainMenuWindow::cmStyle()
{
  int icon;

  if (++GameStyle == NoGameStyles)
    GameStyle = 0;
  switch (GameStyle)
  {
    default:
    case SQUARES:   field = squarefield;  icon = MENUSQUARES;	break;
    case HEXAGONS:  field = recthexfield; icon = MENUHEXAGONS;	break;
    case HEXAGONAL: field = hexagonfield; icon = MENUHEXAGONAL; break;
  }
  StyleButton->ChangeIcon(MenuIcon[icon]);
  StyleButton->Paint();
  StyleButton->RefreshWindow();

  Main->cmGame(true);			// In case new style doesn't allow wrap
  field->AdjustWrap();
  field->NewGame();
}


// Use the game button to display the current game and to select a new one.
void MainMenuWindow::cmGame(bool UpdateOnly)
{
  if (!UpdateOnly)
  {
    if (field->GameProgress() == PLAYING)
      return;
    Game = CLEAR + CROSS - Game;
    field->AdjustWrap();
    field->NewGame();
  }

  int icon = (Game == CROSS)	  ? MENUCROSS :
	     (Start == PERIMETER) ? MENUPERIMETER :
	     (field->canWrap())   ? MENUWRAP : MENUCLEAR;
  GameButton->ChangeIcon(MenuIcon[icon]);
  GameButton->Paint();
  GameButton->RefreshWindow();
  Board->DisplayFace();
}


// Use the automatic button to display the automatic options and select a new
// one. The order is:
//   No Automatic -> AutoMark -> AutoOpen -> Both Automatics.
void MainMenuWindow::cmAuto(bool UpdateOnly)
{
  if (field->GameProgress() == PLAYING)
    return;

  if (!UpdateOnly)
  {
    if (!isAutoMark && !isAutoOpen)
      isAutoMark = true;
    else if (isAutoMark && !isAutoOpen)
    {
      isAutoMark = false;
      isAutoOpen = true;
    }
    else if (!isAutoMark && isAutoOpen)
      isAutoMark = true;
    else // isAutoMark && isAutoOpen
    {
      isAutoMark = isAutoOpen = false;
    }
  }

  int icon = isAutoMark + isAutoOpen*2 + MENUNONE;
  AutoButton->ChangeIcon(MenuIcon[icon]);
  AutoButton->Paint();
  AutoButton->RefreshWindow();
  Board->DisplayFace();
}


// Since TWS has no check menu item, but it does display a changed name,
// use the square brackets to make a box to indicate the current hint state.
void MainMenuWindow::cmHints(int hint)
{
  HelpMenuRes[Hints].Text[0] =
  HelpMenuRes[Hints].Text[1] = ' ';
  Hints = hint;
  HelpMenuRes[Hints].Text[0] = '[';
  HelpMenuRes[Hints].Text[1] = ']';

  if (field->GameProgress() != NOT_PLAYING && !Board->Paused())
  {
    field->ShowHints();
    Board->Display();
  }

  if (Hints > hintsused)
    hintsused = Hints;
  Board->DisplayFace();
}


// Update and display the current time, ensuring it's displayed using the
// system font (since fixed font could be in use).
void MainMenuWindow::Timer()
{
  struct time new_time;
  gettime(&new_time);
  if (new_time.ti_min == old_time.ti_min)
    return;
  old_time = new_time;
  char buffer[6];
  sprintf(buffer, "%d:%02d", old_time.ti_hour, old_time.ti_min);
  if (SysFont == FixedFont)
  {
    SysFont = SysFont1;
    tym->SetText(buffer);
    SysFont = FixedFont;
  }
  else
    tym->SetText(buffer);
}
